home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / ada / gwuada_9.zip / ADALEX.C < prev    next >
C/C++ Source or Header  |  1993-07-27  |  22KB  |  807 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9.  
  10. /*            Lexical scanner for ADA 
  11.  
  12. One line of text at a time is read in using getline(). Tokens are scanned
  13. for, and gettok() returns one token at a time to the parser. What is actually
  14. returned is a pointer to a structure for the parse stack capable of holding
  15. the token. No initialization is needed, as it has all been done statically
  16. (before run time).
  17. */
  18.  
  19. /* define PDEBUG to get some debug trace output */
  20.  
  21. #include "hdr.h"
  22. #include "adalex.h"
  23. #include "miscp.h"
  24. #include "errsp.h"
  25. #include "adalexp.h"
  26.  
  27. static int getline();
  28. static struct prsstack *newtoken(int, int, int, int);
  29. static int isdecimal(char);
  30. static int ishex(char);
  31. static int isletterordigit(char);
  32. static int scanidorint(char *, int *, int *, int (*func)(char), int);
  33. static void scanexp(char *, int *, int *);
  34. static int scandec(char *, int *, int *, int (*func)(char));
  35. static void checkbased(char *, int *);
  36. static void convtoupper(char *);
  37. static void nlisthash(int, int *, int *);
  38. static int newnode(char *, int, int);
  39.  
  40. /* Global variables */
  41.  
  42. int lineno = 0;                    /* Current line number in adafile */
  43. int colno;                        /* Current column number in adafile */
  44.  
  45. char *data = (char *)source_buf[0];        /* Current line of ada program */
  46. char *line = (char *)source_buf[0];        /* Pointer to character within data array */
  47. /* These are initialized so that an end of line is indicated */
  48.  
  49. char *nonprintingmsg[] = {    /* Messages for non-printing characters */
  50.     "NUL (^@)",
  51.     "SOH (^A)",
  52.     "STX (^B)",
  53.     "ETX (^C)",
  54.     "EOT (^D)",
  55.     "ENQ (^E)",
  56.     "ACK (^F)",
  57.     "BEL (^G)",
  58.     "BS (^H)",
  59.     "HT (^I)",
  60.     "LF (^J)",
  61.     "VT (^K)",
  62.     "FF (^L)",
  63.     "CR (^M)",
  64.     "SO (^N)",
  65.     "SI (^O)",
  66.     "DLE (^P)",
  67.     "DC1 (^Q)",
  68.     "DC2 (^R)",
  69.     "DC3 (^S)",
  70.     "DC4 (^T)",
  71.     "NAK (^U)",
  72.     "SYN (^V)",
  73.     "ETB (^W)",
  74.     "CAN (^X)",
  75.     "EM (^Y)",
  76.     "SUB (^Z)",
  77.     "ESC",
  78.     "FS",
  79.     "GS",
  80.     "RS",
  81.     "US"};
  82. char source_buf[NUM_LINES][MAXLINE + 1] = { '\0' }; /* Source lines buffer */
  83. int src_index = -1;        /* Index into source lines buffer */
  84.  
  85.  
  86. /* Getline: Read a line into data, returning EOF on end of file.
  87.     ^J, ^K, ^L, ^M (10-13) are all interpreted as end of line. 
  88.     Line, lineno, and colno    are set as neeeded. */
  89.  
  90. /* Note: At present, the listing of the ada source file is done after
  91.    reading the line, in getline(). Because the source file may have tabs,
  92.    in order to insure that the relative spacing of the characters in the
  93.    source file appears correctly on the screen and that underlining of
  94.    errors occurs correctly, the number of characters printed on each
  95.    line before the next source line should be a multiple of 8 (tab stops
  96.    are at 8k+1). At present we leave 5 spaces for the line number, print
  97.    a colon (:), and leave 2 more spaces before printing the source line for
  98.    a total of 8 spaces.
  99. */
  100.  
  101. /* A buffer of NUM_LINES source lines is kept for the purpose of printing
  102.    error messages. Source_buf is the buffer, src_index is the index into
  103.    the buffer for the current line.
  104. */
  105.  
  106. /*
  107. #include "d:\ed\edit.h"
  108. extern AVL_EDIT_WINDOW_PTR avl_w;
  109. AVL_LINE_PTR avl_temp;
  110.  
  111.     
  112. int AVL_GETC()
  113. {
  114.     char txt[100];
  115.     struct rccoord old;
  116.     if (avl_w -> txt_pos >= strlen(avl_w -> current_line -> line))  {
  117.         avl_w -> current_line = avl_w -> current_line -> next;
  118.         avl_w -> txt_pos = 0;
  119.         if (avl_w -> current_line == avl_w -> head)
  120.             return(EOF);
  121.         
  122.         old = _settextposition(1, 17);
  123.         sprintf(txt,"%4d", avl_w -> current_line -> line_no - 1);  
  124.         _outtext(txt);
  125.         return '\n';
  126.         }
  127.     if (avl_w -> current_line -> line [ avl_w -> txt_pos] == 1)
  128.         return EOF;
  129.     return avl_w -> current_line -> line [avl_w -> txt_pos++];
  130. }
  131.  
  132. */
  133.  
  134. static int getline()                                            /*;getline*/
  135. {
  136.     int ch, ind = 0;
  137.  
  138. /*    if (avl_w -> current_line == avl_w -> head) */
  139.     if (feof(adafile))  
  140.         return(EOF);
  141.     src_index = (src_index + 1) % NUM_LINES;
  142.     line = data = source_buf[src_index];
  143.     lineno++;
  144.     colno = 1;
  145.     for (;;) {
  146.         ch = /*  AVL_GETC(); */  getc(adafile); 
  147.         if (ch==EOF) break;
  148.         if (ch <= 13 && ch >= 10) break;
  149.         if (ind == MAXLINE) {
  150.             char msg[80];
  151.             sprintf(msg,
  152.               "Line %d exceeds maximum length, truncated to %d characters",
  153.               lineno, MAXLINE);
  154.             lexerr(lineno, 1, 1, msg);
  155.             while ((ch = getc(adafile)) != EOF && !(ch<=13 && ch>=10));
  156.             break;
  157.         }
  158.         else {
  159.             data[ind++] = ch;
  160.         }
  161.     }
  162.  
  163.     data[ind] = '\0';
  164.     if (ch == EOF && !ind)
  165.         return(EOF);
  166. #ifdef DEBUG
  167.     if (trcopt)
  168.         fprintf(errfile, "%5d:    %s\n", lineno, data);
  169.     if (termopt)
  170.         printf(         "%5d:    %s\n", lineno, data);
  171. #endif    
  172.     return(0);
  173. }
  174.  
  175. static struct prsstack *newtoken(int num, int index, int line, int col)
  176.                                                                 /*;newtoken*/
  177. {
  178.     /* Newtoken: allocate memory for a new token structure, and initialize */
  179.     /* the fields of the structure. */
  180.  
  181.     struct prsstack *tok;
  182.  
  183.     tok = PRSALLOC();
  184.     tok->symbol = num;
  185.     tok->ptr.token = TOKALLOC();
  186.     tok->ptr.token->index = index;
  187.     tok->ptr.token->span.line = line;
  188.     tok->ptr.token->span.col = col;
  189.     return(tok);
  190. }
  191.  
  192. /* Functions for passing to scanidorint */
  193.  
  194. static int isdecimal(char ch)                                    /*;isdecimal*/
  195. {
  196.     return(isdigit(ch));
  197. }
  198.  
  199. static int ishex(char ch)                                        /*;ishex*/
  200. {
  201.     return(isdigit(ch) || 'A' <= ch && ch <= 'F' || 'a' <= ch && ch <= 'f');
  202. }
  203.  
  204. static int isletterordigit(char ch)                        /*;isletterordigit*/
  205. {
  206.     return(isalpha(ch) || isdigit(ch));
  207. }
  208.  
  209. struct prsstack *gettok()                                        /*;gettok*/
  210. {
  211.     /* Gettok: Scan and return the next token in the adafile, adding the */
  212.     /* token to namelist. */
  213.  
  214.     static int nextcanbeprime = 0;    /* The next token can be a prime */
  215.     static int canbeprime;            /* The current token can be a prime */
  216.     struct prsstack *tok;            /* Token to be returned */
  217.  
  218.     while (1) {
  219.         while (1) {
  220.             while (*line == ' ' || *line == '\t') {
  221.                 colno += (*line == '\t') ? (8 - ((colno - 1) % 8)) : 1;
  222.                 line++;
  223.             }
  224.             if (!*line || *line == '-' && line[1] == '-')
  225.                 break;
  226.             canbeprime = nextcanbeprime;
  227.             nextcanbeprime = 0;
  228.  
  229.             if (isalpha(*line)) {        /* Scan identifiers */
  230.                 char id[MAXLINE + 1];
  231.                 int idind = 0, chread = 0;
  232.                 int tokind, toksym;
  233.  
  234.                 scanidorint(id, &idind, &chread, isletterordigit, 0);
  235.                 if (id[idind - 1] == '_')
  236.                     idind--;
  237.                 id[idind] = '\0';
  238.                 convtoupper(id);
  239.                 tokind = namemap(id, idind);
  240.                 toksym = MIN(tokind, ID_SYM);
  241.                 tok = newtoken(toksym, tokind, lineno, colno);
  242.                 nextcanbeprime = toksym == ID_SYM || toksym == RANGE_SYM
  243.                   || toksym == ALL_SYM;
  244.                 colno += chread;
  245.                 line += chread;
  246.                 return(tok);
  247.             }
  248.  
  249.             else if (isdigit(*line) || *line == '.' && isdigit(line[1])) {
  250.             /* Scan numeric literals */
  251.                 char num[MAXLINE + 3];
  252.                 int ind = 0, chread = 0, result;
  253.                 char ch;
  254.                 /* ind is the index into the num string */
  255.                 /* chread is the index into the line input string */
  256.  
  257.                 result = scandec(num, &ind, &chread, isdecimal);
  258.                 ch = line[chread];
  259.                 if (result == 1 && (ch == '#' || ch == ':')) {
  260.                 /* Scan for the rest of a based literal */
  261.                     num[ind++] = '#';
  262.                     chread++;
  263.                     if (!scandec(num, &ind, &chread, ishex)) {
  264.                         lexerr(lineno, colno + chread - 1, colno + chread - 1,
  265.                           "Incomplete based number");
  266.                         num[ind++] = '0';
  267.                     }
  268.                     num[ind++] = '#';
  269.                     if (line[chread] != ch) {
  270.                         if (line[chread] == '#' + ':' - ch) {
  271.                             lexerr(lineno, colno + chread, colno + chread,
  272.                               "Expect #'s or :'s in based number to match");
  273.                             chread++;
  274.                         }
  275.                         else {
  276.                             char msg[50];
  277.  
  278.                             sprintf(msg, "Expect '%c' after last digit", ch);
  279.                             lexerr(lineno, colno + chread - 1,
  280.                               colno + chread - 1, msg);
  281.                         }
  282.                     }
  283.                     else
  284.                         chread++;
  285.                     checkbased(num, &ind);
  286.                 }
  287.                 scanexp(num, &ind, &chread);
  288.                 if (isalpha(line[chread]))
  289.                     lexerr(lineno, colno, colno + chread - 1,
  290.                       "Number should be separated from adjacent identifier");
  291.                 num[ind] = '\0';
  292.                 tok = newtoken(NUMBER_SYM, namemap(num, ind), lineno, colno);
  293.                 colno += chread;
  294.                 line += chread;
  295.                 return(tok);
  296.             }
  297.  
  298.             else if (*line == '\'') {
  299.                 int err = 0;
  300.  
  301.                 if (line[1] != '\0' && line[2] == '\'' &&
  302.                     (!canbeprime || line[1]